package com.lt.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * @author lucine
 * @version 1.0 2022/4/13 14:53
 */
@Component
public class RabbitmqConfig {

    private static final Logger logger = LoggerFactory.getLogger(RabbitmqConfig.class);
    @Autowired
    CachingConnectionFactory cachingConnectionFactory;

    @Bean
    RabbitTemplate rabbitTemplate() {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(cachingConnectionFactory);

        rabbitTemplate.setMandatory(true);

        //回调是检验消息是否达到交换机的一个机制
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            CorrelationDataExt correlationDataExt = (CorrelationDataExt) correlationData;
            try{
                logger.info("correlationData ->" + (CorrelationDataExt)correlationData);
                logger.info("ack ->" + ack);
                logger.info("cause ->" + cause);
                if(5 == correlationDataExt.getCount()){
                    //todo 保存到数据库中,后续人工处理
                }else {
                    if (ack) {
                        logger.info("消息发送成功");
                        //todo 修改数据库中的记录，消息投递成功
                    } else {
                        logger.info("消息发送失败");
                        //todo 修改数据库中的记录，消息投递失败
                        correlationDataExt.setCount(correlationDataExt.getCount()+1);
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
                //todo 保存到数据库中
            }
        });

        //只有在交换机到达队列失败的时候才会被触发，当这个回调函数被调用的时候，
        rabbitTemplate.setReturnsCallback((msg) -> {
            //如果是延迟队列，不用处理， 因为只是在交换器上暂存，等过期时间到了 才会发往队列。
            //todo 但是实际延迟队列的保存了怎么办？？？
            if(DelayedQueueConfig.DELAYED_EXCHANGE_NAME.equals(msg.getExchange())){
                return;
            }
            logger.info("setReturnsCallback: msg " + msg.getMessage());
            logger.info("setReturnsCallback: repCode " + msg.getReplyCode());
            logger.info("setReturnsCallback: repText " + msg.getReplyText());
            logger.info("setReturnsCallback: exchange " + msg.getExchange());
            logger.info("setReturnsCallback: routingkey " + msg.getRoutingKey());
            //todo 保存到数据库中
        });
        return rabbitTemplate;
    }
}
